package com.lzx.lizhenxing.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.lzx.lizhenxing.common.config.RabbitMQConfig;
import com.lzx.lizhenxing.common.constrants.CommonConstants;
import com.lzx.lizhenxing.common.exception.CommonException;
import com.lzx.lizhenxing.common.utils.OrderNoUtil;
import com.lzx.lizhenxing.common.utils.SnowflakeIdGenerator;
import com.lzx.lizhenxing.common.utils.UserUtils;
import com.lzx.lizhenxing.common.vo.PageVo;
import com.lzx.lizhenxing.delivery.dao.DeliveryPersonTaskDao;
import com.lzx.lizhenxing.delivery.model.DeliveryPersonTaskModel;
import com.lzx.lizhenxing.pay.service.TradeOrderPayService;
import com.lzx.lizhenxing.point.enums.PointTypeEnum;
import com.lzx.lizhenxing.point.utils.PointUtils;
import com.lzx.lizhenxing.sys.dao.UserDao;
import com.lzx.lizhenxing.sys.model.User;
import com.lzx.lizhenxing.user.dao.UserExpressDeliveryDao;
import com.lzx.lizhenxing.user.dao.UserOrderDao;
import com.lzx.lizhenxing.user.model.UserExpressDeliveryModel;
import com.lzx.lizhenxing.user.model.UserOrderModel;
import com.lzx.lizhenxing.user.param.CreateOrderParam;
import com.lzx.lizhenxing.user.param.OrderQueryParam;
import com.lzx.lizhenxing.user.param.QueryOrderParam;
import com.lzx.lizhenxing.user.param.UpdateTimeParam;
import com.lzx.lizhenxing.user.service.UserOrderService;
import com.lzx.lizhenxing.user.utils.OrderUtils;
import com.lzx.lizhenxing.user.vo.OrderPageVo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

@Service
public class UserOrderServiceImpl implements UserOrderService {

    @Resource
    private UserOrderDao userOrderDao;

    @Resource
    private UserExpressDeliveryDao userExpressDeliveryDao;

    @Resource
    @Lazy
    private TradeOrderPayService tradeOrderPayService;

    @Resource
    private UserDao userDao;

    @Resource
    private DeliveryPersonTaskDao deliveryPersonTaskDao;

    @Resource
    private PointUtils pointUtils;

    @Resource
    private OrderUtils orderUtils;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOrder(CreateOrderParam param) {
        // 先查这个快递有没有创建过订单
        UserOrderModel order = userOrderDao.selectByExpressDeliveryId(param.getExpressDeliveryId());
        if (Objects.nonNull(order)) {
            throw new CommonException(CommonConstants.ERROR, "该快递已经创建过代取订单");
        }
        UserOrderModel orderModel = new UserOrderModel();
        // 这里直接使用雪花算法生成id，否则在向配送员任务表中添加任务的时候获取不到订单的id
        SnowflakeIdGenerator generator = new SnowflakeIdGenerator(1, 1);
        orderModel.setId(generator.generateId());
        // 订单编码需要手动生成
        String orderNo = OrderNoUtil.generateUniqueTradeNo();
        orderModel.setOrderNo(orderNo);
        // uid从当前线程的threadlocal中获取
        Long uid = UserUtils.getUser();
        // 其余的属性使用前端传的属性
        BeanUtils.copyProperties(param, orderModel);
        orderModel.setUid(uid);
        UserExpressDeliveryModel edModel = userExpressDeliveryDao.selectById(param.getExpressDeliveryId());
        // 如果是积分支付，需要扣除对应用户的积分,并设置对应的订单为已支付
        if (Objects.equals(0, param.getPayType())) {
            orderUtils.payByPoint(uid, orderModel, edModel);
        } else {
            // 否则就是支付宝支付
            // 设置订单状态为未支付
            orderModel.setStatus(0);
            // 将快递表的该快递的状态设置为待支付（3）
            edModel.setStatus(3);
        }
        // 插入数据库并返回订单的id
        userOrderDao.insert(orderModel);
        userExpressDeliveryDao.updateById(edModel);
        // 使用mq发送一条30分钟过期时间的消息
        // 发送延迟消息到 RabbitMQ
        rabbitTemplate.convertAndSend(
                RabbitMQConfig.ORDER_DELAY_QUEUE,
                orderModel.getId(),
                message -> {
                    // 设置消息过期时间 30 分钟（单位：毫秒）
                    message.getMessageProperties().setExpiration("60000*30");
                    return message;
                }
        );
        return orderModel.getId();
    }

    @Override
    public void dealOrder(String orderNo) {
        /**
         * 订单状态设置为配送中
         */
        LambdaQueryWrapper<UserOrderModel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserOrderModel::getOrderNo, orderNo);
        UserOrderModel order = userOrderDao.selectOne(queryWrapper);
        order.setStatus(1);
        // 设置支付方式为支付宝支付
        order.setPayType(0);
        userOrderDao.updateById(order);
        /**
         * 快递的状态设置为代取中
         */
        Long exDeId = order.getExpressDeliveryId();
        UserExpressDeliveryModel exDeModel = userExpressDeliveryDao.selectById(exDeId);
        exDeModel.setStatus(2);
        userExpressDeliveryDao.updateById(exDeModel);
        /**
         * 给对应的配送员添加配送任务
         */
        DeliveryPersonTaskModel taskModel = new DeliveryPersonTaskModel();
        taskModel.setStatus(0);
        taskModel.setUid(order.getDeliveryPersonId());
        taskModel.setUserExpressDeliveryId(exDeModel.getId());
        taskModel.setUserOrderId(order.getId());
        deliveryPersonTaskDao.insert(taskModel);
    }

    @Override
    public PageVo<OrderPageVo> getPageOrder(OrderQueryParam param) {
        Long uid = UserUtils.getUser();
        // PageHelper分页插件,该处作用是向sql中拼接limit条件
        PageHelper.startPage(param.getPageNum(), param.getPageSize());

        // 获取查询结果
        List<OrderPageVo> orderVoList = userOrderDao.selectPageAll(uid, param.getBillNum(), param.getCourierCompany());

        // 构造 PageVo 返回分页数据
        PageVo<OrderPageVo> pageVo = new PageVo<>();
        pageVo.setTotal(orderVoList.size());
        pageVo.setDataList(orderVoList);

        return pageVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrder(Long id) {
        UserOrderModel userOrder = userOrderDao.selectById(id);
//        if(userOrder.getStatus() == 1){
//            throw new CommonException(500,"配送中的订单不能取消");
//        }
        /**
         * 取消订单：
         *        1.该用户的订单表中删除该订单，同时需要原路退回金钱，如果是积分支付需要退回积分
         *        2.平台快递表中将该快递状态更改为已到达 status = 1
         *        3.配送员的配送表中，删除该任务，通过userOrderId（前端传的id）删除
         */

        // 1.该用户的订单表中删除该订单，同时需要原路退回金钱,如果是积分支付需要退回积分
        if (Objects.equals(1, userOrder.getPayType())) {
            Long uid = UserUtils.getUser();
            pointUtils.insertPoint(uid, 10, PointTypeEnum.TYPE_ORDER_DELETE.getType());
            User user = userDao.selectById(uid);
            user.setPoint(user.getPoint() + 10);
            userDao.updateById(user);
        } else if (Objects.equals(0, userOrder.getPayType())) {
            //如果是支付宝支付，退回金钱
            tradeOrderPayService.tradePayRefund(id);
        }
        userOrderDao.deleteById(id);
        // 2.平台快递表中将该快递状态更改为已到达 status = 1
        UserExpressDeliveryModel exDeModel = userExpressDeliveryDao.selectById(userOrder.getExpressDeliveryId());
        exDeModel.setStatus(1);
        userExpressDeliveryDao.updateById(exDeModel);
        // 3.配送员的配送表中，删除该任务，通过userOrderId（前端传的id）删除
        LambdaQueryWrapper<DeliveryPersonTaskModel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DeliveryPersonTaskModel::getUserOrderId, id);
        deliveryPersonTaskDao.delete(queryWrapper);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDeliveryTime(UpdateTimeParam param) {

        UserOrderModel order = userOrderDao.selectById(param.getOrderId());
        order.setDeliveryTime(param.getDeliveryTime());
        userOrderDao.updateById(order);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOrderInfo(Long id) {
        UserOrderModel userOrder = userOrderDao.selectById(id);
        if(Objects.equals(2, userOrder.getStatus())){
            userOrderDao.deleteById(id);
        } else {
            throw new CommonException(500, "未完成的订单不允许删除");
        }

    }

    @Override
    public UserOrderModel getOneOrder(QueryOrderParam param) {
        LambdaQueryWrapper<UserOrderModel> queryWrapper = new LambdaQueryWrapper<>();
        if(Objects.nonNull(param.getId())){
            queryWrapper.eq(UserOrderModel::getId, param.getId());
        }
        if (Objects.nonNull(param.getExpressDeliveryId())) {
            queryWrapper.eq(UserOrderModel::getExpressDeliveryId, param.getExpressDeliveryId());
        }
        return userOrderDao.selectOne(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void payByPoint(Long orderId) {
        Long uid = UserUtils.getUser();
        UserOrderModel orderModel = userOrderDao.selectById(orderId);
        UserExpressDeliveryModel edModel = userExpressDeliveryDao.selectById(orderModel.getExpressDeliveryId());
        orderUtils.payByPoint(uid,orderModel,edModel);
        userOrderDao.updateById(orderModel);
        userExpressDeliveryDao.updateById(edModel);
    }

    @Override
    public String getOrderNo(Long orderId) {
        UserOrderModel orderModel = userOrderDao.selectById(orderId);
        if(Objects.isNull(orderModel)){
            throw new CommonException(CommonConstants.ERROR,"未找到订单");
        }
        return orderModel.getOrderNo();
    }

}
